﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(Animator))]
public class AnimationBehaviour : UpdateableComponent {
    [HideInInspector]
    public Animator animator;

    protected bool _isPlaying;
    protected string _objectStateName;

    Queue<KeyValuePair<string, Action>> _actionQueue = new Queue<KeyValuePair<string, Action>>();

    void Awake() {
        animator = GetComponent<Animator>();
	}

    public override void OnUpdate(float dt) {
        base.OnUpdate(dt);
        
        if (_isPlaying) {
            var stateInfo = animator.GetCurrentAnimatorStateInfo(0);
     
            if (stateInfo.normalizedTime >= 1f) {
                if (_actionQueue.Count > 0) {
                    var action = _actionQueue.Dequeue().Value;

                    if (action != null) {
                        action();
                    }
                }

                _isPlaying = false;
            }
        }
    }

    public AnimationBehaviour Play(string stateName, string sfxPath = null) {
        if (!string.IsNullOrEmpty(sfxPath)) {
            AudioManager.Instance.PlaySound(sfxPath);
        }

        animator.Play(stateName, -1, 0f);

        // 为保证在下一帧运行的动画状态为Play()方法所触发的状态
        StartCoroutine(TimeUtility.WaitForEndOfFrame(() => _isPlaying = true));
        
        _objectStateName = gameObject.name + ": " + stateName;
        return this;
    }

    public AnimationBehaviour SetTrigger(string triggerName, string sfxPath = null) {
        animator.SetTrigger(triggerName);

        // 为保证在下一次运行的动画状态为SetTrigger()方法所触发的状态
        // Unity默认动画间的过渡时间为 0.25s，如果有自行更改需注意
        StartCoroutine(TimeUtility.DelayInvoke(0.25f, () => _isPlaying = true));

        if (!string.IsNullOrEmpty(sfxPath)) {
            AudioManager.Instance.PlaySound(sfxPath);
        }

        _objectStateName = gameObject.name + ": " + triggerName;
        return this;
    }

    public void PlaySequence(string beginStateName, string voicePath, Action callback = null) {
        Play(beginStateName).OnFinished(() => {
            var duration = AudioManager.Instance.PlaySound(voicePath).Length;
            SetTrigger("ToNext");
            StartCoroutine(TimeUtility.DelayInvoke(duration, () => SetTrigger("ToNext").OnFinished(callback)));
        });
    }

    public void OnFinished(Action callback) {
        _actionQueue.Enqueue(new KeyValuePair<string, Action>(_objectStateName, callback));
    }
}
